המחלקה:
[b][/b]
class Sidox_Datebase extends PDO {
private $_bind; #Linking the database with data
private $_search; #Search Settings
protected $_table; #Save a database table
function __construct($dsn, $username, $password, $table) {
parent::__construct($dsn, $username, $password);
$this->_table = $table;
}
/*
* set in _bind name and value
*/
function __set($name, $value) {
$this->_bind['name'][] = " `$name` ";
$this->_bind['value'][] = " '$value' ";
}
/*
* Insert into database
*/
public function save() {
$sql = 'INSERT INTO `' . $this->_table . '` (
' . implode(',', $this->_bind['name']) . ' ) VALUES (
' . implode(',', $this->_bind['value']) . ' )';
$this->clean();
return $this->query($sql);
}
/*
* Update into database
*/
public function update() {
$sql = null;
foreach ($this->_bind['name'] as $key => $value) {
$sql[] = " {$this->_bind['name'][$key]} = {$this->_bind['value'][$key]} ";
}
$sql = 'UPDATE `' . $this->_table . '` SET ' . implode(' , ', $sql) . ' WHERE ' . implode(' AND ', $this->_search);
$this->clean();
return $this->query($sql);
}
/*
* Delete from database
*/
public function delete() {
$sql = 'DELETE FROM `' . $this->_table . '` WHERE ' . implode(' AND ', $this->_search);
$this->clean();
$row = $this->query($sql);
return $row->fetch();
}
/*
* set search settings
*/
public function setWhere($name, $value) {
$this->_search[] = " `$name` = '$value' ";
return $this;
}
/*
* get rows with settings
*/
public function getRow() {
$sql = 'SELECT * FROM `' . $this->_table . '` WHERE ' . implode(' AND ', $this->_search);
$this->clean();
$row = $this->query($sql);
return $row->fetch();
}
/*
* clean all data in class
*/
public function clean() {
$this->_search = null;
$this->_bind = array();
}
/*
* get all from database
*/
public function getAll() {
$sql = 'SELECT * FROM `' . $this->_table;
$row = $this->query($sql);
return $row->fetchAll();
}
}
דוגמה לשימוש:
מסד נתונים לדוגמה:
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) NOT NULL,
`password` varchar(32) NOT NULL,
`email` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
דוגמה לשימוש במחלקה
$db = Sidox_Datebase("mysql:host=localhost;dbname=demo", 'root', '', 'demo');
//Insert to db
$db->username = 'pol';
$db->password = 'pass';
$db->email = '[email protected]';
$db->save();
$db->username = 'pol1';
$db->password = 'pass1';
$db->email = '[email protected]';
$db->save();
$row =$db->setWhere('name','pol')->setWhere('password','pass')->getRow(): //can used to login...
echo "<pre>";
print_r($row);
echo "<br />";
$row = $db->getAll();
print_r($row);
$db->username = 'pol2';
$db->password = 'pass2';
$db->email = '[email protected]';
$db->setWhere('name','pol')->update();
//now pol is pol2
$db->setWhere('name','pol')->delete();
13 תשובות
1) למה המתודה setWhere קובעת בדיקה האם הערכים זהים? מה תעשה כשתרצה לבדוק הם הערך הראשון גדול מהשני?
תעביר ל-setWhere ארגומנט אחד שיהיה ביטוי שיתאים ל-WHERE, כלומר משהו כזה:
2) לא ברור לי הקשר הלוגי של המתודות שלך. לדוגמה, הקוד הזה:
לא אומר כלום והוא לא תקין. אתה אומר "המסד-קובע תנאי-קובע תנאי-מוציא שורה". זה אמור להיות "מסד-שורות שצריך לקחת-קובע תנאי (אולי מס' תנאי במכה אחת)-מוציא שורה".
3) במקום __set וכל הלולאות שאתה עושה, צור את המתודות שיקבלו ארגומנטים דינמיים ושאוב אותם באמצעות func_get_args. זה מתאים למקרים שבהם אתה לא יודע את כמות הפרמטרים שתקבל. המתודות שלך כרגע נראות גרוע מאוד, והמחלקה עצמה גם כן.
תלמד לכתוב מתודות לטוח ארוך, כלומר שהן יהיו יותר גמישות ויותר אוניברסליות. אני לא הייתי משתמש ב-wrapper שכתבת.
תודה לא חשבתי על זה שיניתי את הGETROW והורדתי את הGETALLROWS
{
$sql = 'SELECT * FROM `' . $this->_table .'` ';
if (func_num_args() > 0)
$sql .= ' WHERE ' . implode(' AND ', func_get_args());
$row = $this->query($sql);
return $row->fetch();
}
עכשיו יש לי שאלה אחרת איזה פונקציה שאני יכניס :
וזה יהפוך את הname = pol ל 'name` = 'pol`?
הפתרון שלי לזה הוא לולאה אבל ניראה לי יש משהו שיכול לעזור בלי
בתור שיפור תעשה ככה שיהיה אפשר ליצור מופעים מהמחלקה שמקושרים לטבלאות שונות.
כלומר מחלקת user שיורשת מהמחלקה שלך תיגש אל טבלת users
מחלקה אחרת שיורשת מהמחלקה הזו תיגש לטבלה אחרת
שידרגתי את זה קצת יש עוד משהו שכידי להוסיף?
המחלקה אמורה להיות חלק בתוך FRAMEWORK שאני עובד אליו אז אני רוצה שזה היה הכי פשוט לשימוש
/*
* **************************
* Sidox db model *
* **************************
*
* how to use:
* 1)connected to sql server
* demo for mysql:
* $obj = new Sidox_Model_Database(
* "mysql:host=localhost;dbname=pol", 'root', 'pass','table'(=null)
* );
* 2)set table
* $obj->table = "tablename";
* 3)for add new information in db use
* $obj->dbColum = 'x';
* $obj->dbColum2 = 'y';
* $obj->save();
* 4)for update information in db use
* $obj->update();
* $obj->dbColum = 'y';
* $obj->dbColum2 = 'x';
* $obj->save('dbColum = x','dbColum2 = y');
* 5)delete information
* $obj->delete('dbColum = y','dbColum2 = x');
* 6)get information
* $obj->getRows('dbColum = y','dbColum2 = x');
* $obj->getRows(); //get all
* 7)order by and limit
* $obj->order('dbColum','DESC')->limit(0,2)->getRows('dbColum = y','dbColum2 = x');
* $obj->order('dbColum','DESC')->limit(0,2)->getRows();
*/
class Sidox_Model_Database extends PDO {
private $_data = null; // @param string Linking the database with data
private $_update = false; // @param bool var use update in function save
private $_scan = null;
public $table = null; // @param string database table
function __construct($dsn, $username, $password, $table = null) {
parent::__construct($dsn, $username, $password);
$this->table = $table;
}
/*
* save params in $_data
* @param $name name of db column
* @param $value the colum value
*/
function __set($name, $value) {
if ($this->_action == 'update') {
$this->_data[] = '`' . $name . '` = \'' . $value . '\'';
}
$this->_data[$name] = " '$value' ";
}
/*
* add mode: save in db new information
* update mode: update the information
* @param $_data save the information
* @param $_update save the mode of function (true = update, false = add)
* @param func_args where to scan for update
* @param $table db table
* @return false or query
*/
public function save() {
if ((empty($this->_data)) && (empty($this->table))) {
return false;
} elseif (($this->_update) && (func_num_args() > 0)) {
//action update
$rtn = $this->query(
'UPDATE `' . $this->table . '` SET ' .
implode(' , ', $this->_data) .
$this->scanWhere(func_get_args())
);
$this->_data = null;
$this->_update = false;
return $rtn;
} elseif ($this->_update == false) {
//action add
$rtn = $this->query(
'INSERT INTO `' . $this->table . '` (
' . implode(' , ', array_keys($this->_data)) . ' ) VALUES (
' . implode(' , ', $this->_data) . ' )'
);
$this->_data = null;
return $rtn;
}
return false;
}
/*
* active the update mode in save function
* @param $_update get true
*/
public function update() {
$this->_update = true;
}
/*
* delete db row
* @param func_args
* @return the query connection
*
*/
public function delete() {
if (func_num_args() > 0)
return $this->query(
'DELETE FROM `' . $this->table .
$this->scanWhere(func_get_args())
);
}
/*
* get DB rows
* @param func_args or null
* @return the query connection
*/
public function getRows() {
$sql = 'SELECT * FROM `' . $this->table . '` ';
if (func_num_args() > 0)
$sql .= $this->scanWhere(func_get_args());
if (!empty($this->_sets)) {
$sql .= " " . $this->_sets;
unset($this->_sets);
}
unset($this->_scan);
return $this->query($sql);
}
/*
* Order By
* @param string $order what order
* @param string $type is ASC or DESC
* @param $_sets test if set if true function die
* @return $this
*/
public function order($order, $type = 'ASC') {
if (isset($this->_sets['order'])) {
return false;
}
$this->_scan .= ' ORDER BY ' . $order . ' ' . $type . ' ';
$this->_sets['order'] = null;
return $this;
}
/*
* limit list
* @param int $limit start limit list or mach of limit
* @param int $endLimit end the limit list
* @param $_sets test if set if true function die
* @return $this
*/
public function limit($limit, $endLint = null) {
if (isset($this->_sets['limit'])) {
return false;
}
if (!empty($endLint))
$this->_scan .= ' LIMIT ' . $limit . ',' . $endLint;
else
$this->_scan .= ' LIMIT ' . $limit;
$this->_sets['limit'] = null;
return $this;
}
/*
* @param Array $scanArgs where scan
* @return where to scan
*/
private function scanWhere($scanArgs) {
for ($i = 0; $i < sizeof($scanArgs); $i++) {
sscanf($scanArgs[$i], '%s %s %s', $key, $operator, $value);
$scanArgs[$i] = ' `' . $key . '` ' . $operator . ' \'' . $value . '\'';
}
return ' WHERE ' . implode(' AND ', $scanArgs);
}
}
השיפור נראה נחמד. כל הכבוד :)
מה שכן, הייתי ממליץ לך לחשוב עד כמה נוח להישתמש במחלקה הזו.
מאוד לא אינטואיטיבי לזכור קודם להעביר ל x->update ואז לעשות save
חוץ מזה למפתח בכלל לא צריך להיות אכפת אם זה update או insert. שהמחלקה תחליט לבד.
בדרך כלל נהוג לעשות ככה, שכל מופע של מחלקה מייצג שורה אחת במסד שאיתה אפשר לעבוד.
מכאן הקוד שיוצא נראה בערך ככה:
$row1->column = 'blabla';
$row1->save(); // makes an update
$newRow = new Table1();
$newRow->columnX = 'yo';
$newRow->save(); // makes an insert
$Alexes = Table1::where(['name' => 'alex']);
// $alexes = array of Table1 instances
$Alexes[0]->name = 'Tony';
$Alexes[0]->save(); // update
אל תשכח להוסיף טיפול בשגיאות, במקרה ולא הוזנו כל שדות החובה למשל.
בנוסף כל הכבוד על שימוש ב PHPDOCS. רק שים לב שאתה כותב את ה-DOC מעל למשתנה או המטודה ולא בצד שלה, אחרת העורך חושב שזה ה-DOC של המשתנה הבא.
כל הסיפור אם הUPDATE גם אני לא אהבתי אבל זאת הדרך היחידה שחשבתי שאני יוכל להיפתר מלולאה
פשוט אין לי רעיון איך להפריד בין מערך כזה מבלי להשתמש בלולאה:
כך שיצא לאחר ההפרדה `username`='pol`,`password`='pass',`email`= '[email protected]'
הפתרון היחיד שהיה לי לזה שימוש בלולאת FOR
כנראה שזה יהיה foreach אבל אין שום בעיה עם לולאה.
רק על תשכח לטפל ב sql injection
תהיה לי מחלקה שאוטומטית מטפלת בכל הקלטים ככה שלא תהיה לי אם זה בעיה היא מנתרת את כל הבעיות
זהו סידרתי את זה ופשוט מעכשיו צריך לרשום save() ברגע שבSAVE יש הגדרות חיפוש הוא מתייחס לזה כעל UPDATE
יש עוד משהו חשוב שכידי להוסיף שיקל על העבודה?
/*
* **************************
* Sidox db model *
* **************************
*
* how to use:
* 1)connected to sql server
* demo for mysql:
* $obj = new Sidox_Model_Database(
* "mysql:host=localhost;dbname=pol", 'root', 'pass','table'(=null)
* );
* 2)set table
* $obj->table = "tablename";
* 3)for add new information in db use
* $obj->dbColum = 'x';
* $obj->dbColum2 = 'y';
* $obj->save();
* 4)for update information in db use
* $obj->dbColum = 'y';
* $obj->dbColum2 = 'x';
* $obj->save('dbColum = x','dbColum2 = y');
* 5)delete information
* $obj->delete('dbColum = y','dbColum2 = x');
* 6)get information
* $obj->getRows('dbColum = y','dbColum2 = x');
* $obj->getRows(); //get all
* 7)order by and limit
* $obj->order('dbColum','DESC')->limit(0,2)->getRows('dbColum = y','dbColum2 = x');
* $obj->order('dbColum','DESC')->limit(0,2)->getRows();
*/
class Sidox_Model_Database extends PDO {
/*
* @param (string) $_data Linking the database with data
*/
private $_data = null;
/*
* @param (string) $_scan scan in db
*/
private $_scan = null;
/*
* @param (string) $table database table
*/
public $table = null;
/*
* use parent construct and set table
*/
function __construct($dsn, $username, $password, $table = null) {
parent::__construct($dsn, $username, $password);
$this->table = $table;
}
/*
* save params in $_data
* @param $name name of db column
* @param $value the colum value
*/
function __set($name, $value) {
if ($this->_action == 'update') {
$this->_data[] = '`' . $name . '` = \'' . $value . '\'';
}
$this->_data[$name] = " '$value' ";
}
/*
* add mode: save in db new information
* update mode: update the information
* @param $_data save the information
* @param $_update save the mode of function (true = update, false = add)
* @param func_args where to scan for update
* @param $table db table
* @param $rtn return data
* @return false or query
*/
public function save() {
$rtn = false;
if ((empty($this->_data)) && (empty($this->table))) {
return false;
} elseif (func_num_args() > 0) {
//action update
$update = null;
foreach ($this->_data as $key => $value) {
if (empty($update)) {
$update = " `{$key}` = '{$value}'";
continue;
}
$update .= " , `{$key}` = '{$value} '";
}
$rtn = $this->query(
'UPDATE `' . $this->table . '` SET ' .
$update . $this->scanWhere(func_get_args())
);
} else {
//action add
$rtn = $this->query(
'INSERT INTO `' . $this->table . '` (
' . implode(' , ', array_keys($this->_data)) . ' ) VALUES (
' . implode(' , ', $this->_data) . ' )'
);
}
$this->_data = null;
return $rtn;
}
/*
* delete db row
* @param func_args
* @return the query connection
*/
public function delete() {
if (func_num_args() > 0)
return $this->query(
'DELETE FROM `' . $this->table .
$this->scanWhere(func_get_args())
);
}
/*
* get DB rows
* @param func_args or null
* @return the query connection
*/
public function getRows() {
$sql = 'SELECT * FROM `' . $this->table . '` ';
if (func_num_args() > 0)
$sql .= $this->scanWhere(func_get_args());
if (!empty($this->_sets)) {
$sql .= " " . $this->_sets;
unset($this->_sets);
}
unset($this->_scan);
return $this->query($sql);
}
/*
* Order By
* @param string $order what order
* @param string $type is ASC or DESC
* @param $_sets test if set if true function die
* @return $this
*/
public function order($order, $type = 'ASC') {
if (isset($this->_sets['order'])) {
return false;
}
$this->_scan .= ' ORDER BY ' . $order . ' ' . $type . ' ';
$this->_sets['order'] = null;
return $this;
}
/*
* limit list
* @param int $limit start limit list or mach of limit
* @param int $endLimit end the limit list
* @param $_sets test if set if true function die
* @return $this
*/
public function limit($limit, $endLint = null) {
if (isset($this->_sets['limit'])) {
return false;
}
if (!empty($endLint))
$this->_scan .= ' LIMIT ' . $limit . ',' . $endLint;
else
$this->_scan .= ' LIMIT ' . $limit;
$this->_sets['limit'] = null;
return $this;
}
/*
* @param Array $scanArgs where scan
* @return where to scan
*/
private function scanWhere($scanArgs) {
for ($i = 0; $i < sizeof($scanArgs); $i++) {
sscanf($scanArgs[$i], '%s %s %s', $key, $operator, $value);
$scanArgs[$i] = ' `' . $key . '` ' . $operator . ' \'' . $value . '\'';
}
return ' WHERE ' . implode(' AND ', $scanArgs);
}
}